import {binary} from '../const.mjs'
import {CALL} from './_cmd'
import Hash from '../lib/hash'
import Cmd from './_cmd'
import {ESK, XPK, EPK, xpkSecret, epk2xpk, ed25519Verify, ed25519Sign} from '../misc/ed25519'
import {encrypt,decrypt} from '../lib/aes'
import * as ipv4 from '../lib/bin/ipv4'
import {second, secondBin} from '../lib/time'
import {dumpUInt48} from '../lib/bin/int'

ESK_HASH = Hash ESK

eskHash = (...args)=>
  Hash ESK_HASH, ...args

NOW = second()
NOW_BIN = dumpUInt48 NOW

setInterval(
  =>
    if NOW % 30 == 0
      NOW = second()
    else
      NOW += 1 # 尾数为1，这样才能遍历所有尾数
    NOW_BIN = dumpUInt48 NOW
  1000
)

export hi = (ip, port)=>
  ipPort = ipv4.dump(ip,port)
  Cmd.HI(
    EPK
    eskHash(
      NOW_BIN
      ipPort
    )[...16]
    NOW_BIN
  )


CALL.HI 32, 32, (epk, h, time, {address,port})=>
  if epk.length < 32 # 防止流量放大攻击
    return

  if 0 == Buffer.compare(epk, EPK)
    return

  Cmd.Q(
    eskHash(
      epk
      NOW_BIN
      ipv4.dump(address,port)
    )[...16]
    NOW_BIN
    h
    time
  )

import Token from '../lib/token'

TOKEN_0 = 2

class TimeOffset
  constructor:->

TIME_OFFSET = new TimeOffset()
#TODO LRU ,  如果时间差小于等于10不记录
# IP_PORT_TIMEOFFSET = new Map()

CALL.Q 16, 6, 16, (q, time, myhash, mytime, {address,port})=>

  if NOW - mytime.readUIntBE(0,6) > 60
    return

  ip = ipv4.dump(address,port)
  # IP_PORT_TIMEOFFSET.set(ip.toString(binary),NOW-time.readUIntBE(0,6))

  # 确认这是是自己发过的hi请求，防止攻击
  if Buffer.compare(
    eskHash(mytime, ip)[...16]
    myhash
  )
    return

  token = await Token(TOKEN_0, q)

  # 签名的内容不应该被一方控制，防止盗取签名
  sign = ed25519Sign Buffer.concat [token, q, ip]

  Cmd.A EPK, sign, token, time, ip

import {verify} from '../lib/token'

CALL.A 32, 64, 8, 6, (epk, sign, token, time, ip, {address,port})=>
  sec = time.readUIntBE(0,6)
  if (NOW - sec) > 60
    return

  q = eskHash(
    epk
    time
    ipv4.dump(address,port)
  )[...16]
  if not verify(
    TOKEN_0
    token
    q
  )
    return

  if not ed25519Verify(
    sign
    Buffer.concat [token, q, ip]
    epk
  )
    return

  xpk = epk2xpk epk
  sk = xpkSecret xpk

  Cmd.PK(
    XPK
    # encrypt sk, time
  )

# 保存对方的pk，可以实现快速重连，跳过以上所有步骤
# 心跳包就是不断重复发送pk的步骤，双方都要跳

CALL.PK (xpk, remote)=>
  # sk = xpkSecret xpk
  console.log remote, xpk.length
#   ip = ipv4.dump(address,port).toString(binary)
#   offset = IP_PORT_TIMEOFFSET.get(ip)
#   offset2 = NOW - time.readUIntBE(0,6)
#   if offset2 != offset
#     diff = offset2 - offset
#     if diff > 60 or diff < -60
#       return
#   else
#     IP_PORT_TIMEOFFSET.set(ip, offset2)
#
#   console.log IP_PORT_TIMEOFFSET
#   if Buffer.compare(Hash(sk,time)[...8], hash)
#     return
#   console.log "活着", "#{address}:#{port} #{size}"
#   return


